package com.zhucai.credit.valid.invoice;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.zhucai.credit.valid.invoice.utils.HttpRequestUtils;
import com.zhucai.credit.valid.invoice.utils.InvoiceUtils;
import com.zhucai.credit.valid.invoice.utils.JacksonUtils;

/**
 * 根据整张图片进行识别查验发票 支持两种方式（url[阿里云oss地址] 和 image[base64字符串]）识别两种方式
 * 
 * @author wuche 应用场景：（1）无法获取客户发票信息只能拿到图片，（2）公司有大量发票不想统计发票详情信息的
 *         缺点：需要图片清晰且发票无损伤才行，识别查询需要时间比查询时间的长
 *
 */

@Component
public class LeShuiOcrVatInfo {
	
	@Value("${invoice.appKey}")
	private String appKey;
	@Value("${invoice.appSecret}")
	private String appSecret;
	
	private static String openUrl = "https://open.leshui365.com";

	public Map getVatInfoByParam(String fileName) throws JsonGenerationException, JsonMappingException, IOException {
		String token = getToken(appKey, appSecret);
		// String token = getToken("111", "222");
		String url = openUrl + "/api/ocrVatInfoForInvoice";
		if (!"".equals(token)) {
			// TODO 不同请求
			Map<String, Object> parameter = getParamByImageData(fileName);
			parameter.put("token", token);
			String requestJson = JacksonUtils.getJsonFromMap(parameter);
			String result = HttpRequestUtils.sendPost(url, requestJson);
			if (StringUtils.isNotEmpty(result)) {
				Map resultMap = JacksonUtils.getMapFromJson(result);
				if (null != resultMap) {
					// 需要重新获取新的token
					if (resultMap.containsKey("error")) {
						String error = (String) resultMap.get("error");
						if ("token error".equals(error)) {
							// TODO 这个错误是token失效
						}
					} else {
						// 返回发票code
						String resultCode = (String) resultMap.get("resultCode");
						// 成功返回发票信息
						if ("1000".equals(resultCode)) {// 获取发票成功
							String invoiceResult = (String) resultMap.get("invoiceResult");
							//System.out.println(invoiceResult);
							// 处理返回成功发票
							return getInviceInfo(invoiceResult);
						} else if ("1001".equals(resultCode)) {// 识别成功，获取发票失败
							// 错误码
							//String invoicefalseCode = (String) resultMap.get("invoicefalseCode");
							// 返回数据是：{"resultMsg":"余额不足，请充值。","invoicefalseCode":"240","isFree":"Y","RtnCode":"00","resultCode":"2001","invoiceResult":""}
							return resultMap;
							/***
							 * 第一种：可以查询，需要检查数据是否正确（扣费的）
							 * 201：发票不存在(第二天查询发票还未上传或者发票代码，发票号码输入有误) 220：发票不一致
							 * （请检查发票日期或者校验码[发票金额] 输入有误 ，注意金额是不含税金额）
							 * 
							 * 第二种：可以查询，需要检查数据是否正确（不扣费） 210
							 * ：代码或号码格式有误（金额有误，校验码有误。。） 211：您输入的发票信息不完全
							 * 230：您输入的发票日期格式不正确，请重新输入（格式2016-01-01）
							 * 
							 * 第三种：可以在次查询（不扣费） 213：查询失败，服务忙 （税局服务不稳定导致的）
							 * 218：税局查验服务暂时不可用，请稍后再试 （税局服务宕机）
							 * 221：您输入的发票正在查询中，请不要重复提交请求
							 * 
							 * 第四种：不能查询 ，需要第二天查的（不扣费） 202：
							 * 查验失败：失败原因，超过该张发票的单日查验次数（5次），请于24小时之后再进行查验
							 * 216：您查询的发票是当日开具的，请于次日查询
							 * 
							 * 第五种：不能查询 （不扣费） 217：过了查票期 （只支持一年发票查询）
							 * 219：您输入的发票暂时不支持查询
							 * 
							 * 第六种：不能查询 ，需要充值（不扣费） 240，余额不足，请充值
							 * 
							 * 第七种：不能查询 需要联系我们（不扣费）
							 * 241，发票查询失败，请联系管理员（我们服务器处理数据异常导致的）
							 * 
							 */
							// TODO 需要您处理不同情况

						} else if ("2001".equals(resultCode)) {// 301：识别失败（图片不清，图片错误，）310：识别接口异常
							//String invoicefalseCode = (String) resultMap.get("invoicefalseCode");
							return resultMap;
						}
					}
				}
			}
		} else {
			System.out.println("ERROR token为空");
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	private static Map getInviceInfo(String invoiceResult)
			throws JsonParseException, JsonMappingException, IOException {
		// 这边是发票数据解析
		Map invoiceResultMap = JacksonUtils.getMapFromJson(invoiceResult);
		String invoiceTypeCode = (String) invoiceResultMap.get("invoiceTypeCode");
		Map resMap = InvoiceUtils.getInoivceInfo(invoiceResultMap, invoiceTypeCode);
		// System.out.println(JacksonUtils.getJsonFromMap(resMap));
		return resMap;
	}

	/**
	 * 获取token
	 * 
	 * @param appKey
	 * @param appSecret
	 * @return
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	private static String getToken(String appKey, String appSecret)
			throws JsonParseException, JsonMappingException, IOException {
		String token = "";
		String tokenRest = HttpRequestUtils.sendGet(openUrl + "/getToken?appKey=" + appKey + "&appSecret=" + appSecret);
		Map<String, Object> tokenMap = JacksonUtils.getMapFromJson(tokenRest);
		if (tokenMap != null && tokenMap.get("token") != null) {
			token = tokenMap.get("token").toString();
		} else {
			// TODO 这边没拿到token原因，1）检查账号是否开通 2）是否修改appSecret
			System.out.println(tokenRest);
		}
		System.out.println(token);
		return token;
	}

	/**
	 * 获取发票查验企业接口请求参数报文
	 * 
	 * @return
	 */
	private static Map<String, Object> getParamByImageData(String fileName) {
		Map<String, Object> rtnMap = new HashMap<String, Object>();
		// String fileName="data/ocrVatInfoForInvoice_demo1.jpg";
		String fileBase64Str = "";
		try {
			byte[] fileData = FileUtils.readFileToByteArray(new File(fileName));
			fileBase64Str = Base64.encodeBase64String(fileData);
		} catch (IOException e) {
			e.printStackTrace();
		}
		rtnMap.put("image", fileBase64Str);
		return rtnMap;
	}

}
